﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.Threading;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace SOEN341_SCHEDULER_PHASE1
{
    public partial class ui_form_Create_Account : Form
    {
        Thread saverThread;
        int formMoveXOffset;
        int formMoveYOffset;
        bool isFormDragged = false;

        public enum textIsGood
        {
            firstName,
            lastName,
            password,
            studentID,
            graduate,
            program,
            email,
            year
        }

        public bool[] isGood = new bool[8];

        public ui_form_Create_Account()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Init all Controls on form 
        /// </summary>
        private void InitFormControls()
        {
            Top = GlobalVariablesClass.LocationMainY;
            Left = GlobalVariablesClass.LocationMainX;

            ui_btn_submit.Enabled = false;

            //init grad list
            ui_list_graduate.SetSelected(0, true);
            ui_lbl_grad.ForeColor = Color.Green;
            isGood[(int)textIsGood.graduate] = true;

            //set tags
            ui_txt_first_name.Tag = ui_lbl_first_name;
            ui_txt_last_name.Tag = ui_lbl_last_name;
            ui_combo_program.Tag = ui_lbl_program;
            ui_combo_year.Tag = ui_lbl_year;
            ui_txt_id.Tag = ui_lbl_id;
            ui_txt_password.Tag = ui_lbl_password;
            ui_txt_email.Tag = ui_lbl_email;

            //init password helpers
            ui_lbl_pwHelpCount.Text = "6+ Characters";
            ui_lbl_pw_helpCapital.Text = "1+ Capital Letter";
            ui_lbl_pw_help_digits.Text = "1+ Digit";

            ui_lbl_pw_helpCapital.ForeColor = Color.Red;
            ui_lbl_pwHelpCount.ForeColor = Color.Red;
            ui_lbl_pw_help_digits.ForeColor = Color.Red;
        }

        private void ui_form_Create_Account_Load(object sender, EventArgs e)
        {
            InitFormControls();
            GenerateProgramList();
        }

        /// <summary>
        /// Generates the program list to display in ui_combo_program
        /// </summary>
        private void GenerateProgramList()
        {
            EducationalProgram[] arrEdu = GlobalVariablesClass.list_EDU_AllPrograms.ToArray();

            for (int i = 0; i < arrEdu.Length; i++)
            {
                ui_combo_program.Items.Add(arrEdu[i]);
            }
        }

        #region VALIDATION

        private void ui_txt_first_name_TextChanged(object sender, EventArgs e)
        {
            //check if not empty if it is set label to red
            TextBox t1 = (TextBox)sender;
            Label t2 = (Label)t1.Tag;

            if (t1.Text.Equals(string.Empty))
            {
                isGood[(int)textIsGood.firstName] = false;
                t2.ForeColor = Color.Red;
            }
            else
            {
                isGood[(int)textIsGood.firstName] = true;
                t2.ForeColor = Color.Green;
            }
        }

        private void ui_txt_last_name_TextChanged(object sender, EventArgs e)
        {
            //check if not empty if it is set label to red
            TextBox t1 = (TextBox)sender;
            Label t2 = (Label)t1.Tag;

            if (t1.Text.Equals(string.Empty))
            {
                isGood[(int)textIsGood.lastName] = false;
                t2.ForeColor = Color.Red;
            }
            else
            {
                isGood[(int)textIsGood.lastName] = true;
                t2.ForeColor = Color.Green;
            }
        }      

        private void ui_txt_password_TextChanged(object sender, EventArgs e)
        {
            bool isPass;
            //verify conditions
            TextBox t1 = (TextBox)sender;
            Label t2 = (Label)t1.Tag;
            string tempText = t1.Text;

            bool foundCap = false;
            bool foundDigit = false;
            bool foundSix = false;

            //length
            if (tempText.Length >= 6)
            {
                foundSix = true;
                ui_lbl_pwHelpCount.ForeColor = Color.Green;
            }
            else
            {
                isPass = false;
                ui_lbl_pwHelpCount.ForeColor = Color.Red;
            }

            //capital letter
            char[] tempChar = tempText.ToCharArray();
            int temper;
            for (int i = 0; i < tempChar.Length; i++)
            {
                temper = (int)tempChar[i];
                if (temper > 64 && temper < 91)
                {
                    foundCap = true;
                    ui_lbl_pw_helpCapital.ForeColor = Color.Green;
                    break;
                }
                ui_lbl_pw_helpCapital.ForeColor = Color.Red;

            }

            //digit
            for (int i = 0; i < tempChar.Length; i++)
            {
                temper = (int)tempChar[i];
                if (temper > 47 && temper < 58)
                {
                    foundDigit = true;
                    ui_lbl_pw_help_digits.ForeColor = Color.Green;
                    break;
                }
                ui_lbl_pw_help_digits.ForeColor = Color.Red;

            }
            if (foundCap && foundDigit && foundSix)
            {
                isGood[(int)textIsGood.password] = true;
                t2.ForeColor = Color.Green;
            }
            else
            {
                isGood[(int)textIsGood.password] = false;
                t2.ForeColor = Color.Red;
            }
        }

        private void ui_txt_id_TextChanged(object sender, EventArgs e)
        {
            //check if not empty if it is set label to red
            TextBox t1 = (TextBox)sender;
            Label t2 = (Label)t1.Tag;
            int test;

            if (t1.Text.Equals(string.Empty))
            {
                isGood[(int)textIsGood.studentID] = false;
                t2.ForeColor = Color.Red;
            }
            else
            {
                //verify if valid number

                try
                {
                    isGood[(int)textIsGood.studentID] = true;
                    int.Parse(t1.Text);
                    t2.ForeColor = Color.Green;
                }
                catch (Exception)
                {
                    isGood[(int)textIsGood.studentID] = false;
                    t2.ForeColor = Color.Red;
                    t1.Text = string.Empty;
                }

            }
        }

        private void ui_txt_first_name_Leave(object sender, EventArgs e)
        {
            //check if not empty if it is set label to red
            TextBox t1 = (TextBox)sender;
            Label t2 = (Label)t1.Tag;

            if (t1.Text.Equals(string.Empty))
            {
                isGood[(int)textIsGood.firstName] = false;
                t2.ForeColor = Color.Red;
            }
            else
            {
                isGood[(int)textIsGood.firstName] = true;
                t2.ForeColor = Color.Green;
            }
        }

        private void ui_txt_last_name_Leave(object sender, EventArgs e)
        {
            //check if not empty if it is set label to red
            TextBox t1 = (TextBox)sender;
            Label t2 = (Label)t1.Tag;

            if (t1.Text.Equals(string.Empty))
            {
                isGood[(int)textIsGood.lastName] = false;
                t2.ForeColor = Color.Red;
            }
            else
            {
                isGood[(int)textIsGood.lastName] = true;
                t2.ForeColor = Color.Green;
            }
        }

        private void ui_txt_id_Leave(object sender, EventArgs e)
        {
            //check if not empty if it is set label to red
            TextBox t1 = (TextBox)sender;
            Label t2 = (Label)t1.Tag;
            int test;

            if (t1.Text.Equals(string.Empty))
            {
                isGood[(int)textIsGood.studentID] = false;
                t2.ForeColor = Color.Red;
            }
            else
            {
                //verify if valid number
                try
                {
                    isGood[(int)textIsGood.studentID] = true;
                    int.Parse(t1.Text);
                    t2.ForeColor = Color.Green;
                }
                catch (Exception)
                {
                    isGood[(int)textIsGood.studentID] = false;
                    t2.ForeColor = Color.Red;
                    t1.Text = string.Empty;
                }

            }
        }

        private void ui_combo_year_Leave(object sender, EventArgs e)
        {
            //check if not empty if it is set label to red
            ComboBox t1 = (ComboBox)sender;
            Label t2 = (Label)t1.Tag;
            int test;

            if (t1.Text.Equals(string.Empty))
            {
                isGood[(int)textIsGood.year] = false;
                t2.ForeColor = Color.Red;
            }
            else
            {
                //verify if valid number

                try
                {
                    isGood[(int)textIsGood.year] = true;
                    int.Parse(t1.Text);
                    t2.ForeColor = Color.Green;
                }
                catch (Exception)
                {
                    isGood[(int)textIsGood.year] = false;
                    t2.ForeColor = Color.Red;
                    t1.Text = string.Empty;
                }

            }
        }

        private void ui_txt_email_Leave(object sender, EventArgs e)
        {
            string patternStrict = @"^(([^<>()[\]\\.,;:\s@\""]+"
                        + @"(\.[^<>()[\]\\.,;:\s@\""]+)*)|(\"".+\""))@"
                        + @"((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"
                        + @"\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+"
                        + @"[a-zA-Z]{2,}))$";
            Regex emailRegex = new Regex(patternStrict);

            string theEmail = ui_txt_email.Text.ToUpper();

            isGood[(int)textIsGood.email] = emailRegex.IsMatch(theEmail);

            Label theErrTag=(Label)ui_txt_email.Tag;

            if (isGood[(int)textIsGood.email])
            {
                theErrTag.ForeColor=Color.Green;
            }
            else
            {
                theErrTag.ForeColor=Color.Red;
            }
        
        }

        private void ui_timer_validator_Tick(object sender, EventArgs e)
        {
            bool isReady = true;
            
            for (int i = 0; i < isGood.Length; i++)
            {
                if (!isGood[i])
                {
                    isReady = false;
                    break;
                }
            }

            ui_btn_submit.Enabled = isReady;
            if (isReady)
            {
                ui_btn_submit.BackColor = Color.LightGreen;
            }
            else
            {
                ui_btn_submit.BackColor = Color.Gray;
            }
        }

        private void ui_combo_program_TextChanged(object sender, EventArgs e)
        {
            //check if not empty if it is set label to red
            ComboBox t1 = (ComboBox)sender;
            Label t2 = (Label)t1.Tag;

            if (t1.Text.Equals(string.Empty))
            {
                isGood[(int)textIsGood.program] = false;
                t2.ForeColor = Color.Red;
            }
            else
            {
                isGood[(int)textIsGood.program] = true;
                t2.ForeColor = Color.Green;
            }

            string toComp = ui_combo_program.Text.ToUpper();

            //try to auto find
            /*
            for (int i = 0; i < ui_combo_program.Items.Count; i++)
            {
                if (ui_combo_program.Items[i].ToString().Contains(toComp))
                {
                    ui_combo_program.SelectedItem = ui_combo_program.Items[i];
                    break;
                }
            }
            */
        }

        private void ui_combo_program_Leave(object sender, EventArgs e)
        {
            //check if not empty if it is set label to red
            ComboBox t1 = (ComboBox)sender;
            Label t2 = (Label)t1.Tag;

            if (t1.Text.Equals(string.Empty))
            {
                isGood[(int)textIsGood.program] = false;
                t2.ForeColor = Color.Red;
            }
            else
            {
                isGood[(int)textIsGood.program] = true;
                t2.ForeColor = Color.Green;
            }
        }

        private void ui_combo_year_TextChanged(object sender, EventArgs e)
        {
            //check if not empty if it is set label to red
            ComboBox t1 = (ComboBox)sender;
            Label t2 = (Label)t1.Tag;
            int test;

            if (t1.Text.Equals(string.Empty))
            {
                isGood[(int)textIsGood.year] = false;
                t2.ForeColor = Color.Red;
            }
            else
            {
                //verify if valid number

                try
                {
                    isGood[(int)textIsGood.year] = true;
                    int.Parse(t1.Text);
                    t2.ForeColor = Color.Green;
                }
                catch (Exception)
                {
                    isGood[(int)textIsGood.year] = false;
                    t2.ForeColor = Color.Red;
                    t1.Text = string.Empty;
                }

            }
        }

        private void ui_txt_email_TextChanged(object sender, EventArgs e)
        {
            string patternStrict = @"^(([^<>()[\]\\.,;:\s@\""]+"
                        + @"(\.[^<>()[\]\\.,;:\s@\""]+)*)|(\"".+\""))@"
                        + @"((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"
                        + @"\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+"
                        + @"[a-zA-Z]{2,}))$";
            Regex emailRegex = new Regex(patternStrict);

            string theEmail = ui_txt_email.Text.ToUpper();

            isGood[(int)textIsGood.email] = emailRegex.IsMatch(theEmail);

            Label theErrTag = (Label)ui_txt_email.Tag;

            if (isGood[(int)textIsGood.email])
            {
                theErrTag.ForeColor = Color.Green;
            }
            else
            {
                theErrTag.ForeColor = Color.Red;
            }
        }

        #endregion

        private void ui_btn_submit_Click(object sender, EventArgs e)
        {
            
            Student studentToCreate;

            string fName = ui_txt_first_name.Text;
            string lName = ui_txt_last_name.Text;
            string password = ui_txt_password.Text;
            long ID = long.Parse(ui_txt_id.Text);
            EducationalProgram eduP = (EducationalProgram)ui_combo_program.SelectedItem;
            int yearOfStudy = int.Parse(ui_combo_year.Text);
            string email = ui_txt_email.Text;

            bool isFound=false;

            Student[] arrStu = GlobalVariablesClass.list_RegisteredStudents.ToArray();

            for (int i = 0; i < arrStu.Length; i++)
            {
                if (arrStu[i].GetID() == ID)
                {
                    isFound = true;
                    break;
                }
            }

            ui_btn_submit.Enabled = false;
            ui_gb_main.Enabled = false;
            ui_lbl_error.Visible = false;
            if (!isFound && eduP!=null)
            {
                GlobalVariablesClass.newAccountName = fName + " " + lName;

                studentToCreate = new Student(eduP, fName, lName, ID, password, null, yearOfStudy, email);
                GlobalVariablesClass.list_RegisteredStudents.Add(studentToCreate);
                SaveStudents();
                ui_btn_submit.BackColor = Color.Green;
                ui_btn_submit.Text = "Saved";
                this.Close();
            }
            else
            {
                ui_btn_submit.Enabled = true;
                ui_gb_main.Enabled = true;

                if (isFound)
                {
                    isGood[(int)textIsGood.studentID] = false;
                    Label tagger = (Label)ui_txt_id.Tag;
                    tagger.ForeColor = Color.Red;
                    ui_txt_id.Text = string.Empty;

                    ui_lbl_error.Visible = true;

                    ui_lbl_error.Text = "This Student ID is already registered!";
                    ui_lbl_error.ForeColor = Color.Red;
                }
                if (eduP == null)
                {
                    isGood[(int)textIsGood.program]=false;
                    Label tagger=(Label)ui_combo_program.Tag;
                    tagger.ForeColor=Color.Red;

                    ui_combo_program.Text = string.Empty;
                    if (ui_lbl_error.Visible)
                    {
                        ui_lbl_error.Text += "\nInvalid program selected (use drop down list)";
                    }
                    else
                    {
                        ui_lbl_error.Text = "Invalid program selected (use drop down list)";
                        ui_lbl_error.ForeColor = Color.Red;
                        ui_lbl_error.Visible = true;
                    }
                }
            }
        }

        /// <summary>
        /// Save students
        /// </summary>
        private void SaveStudents()
        {
            Student[] arrStud = GlobalVariablesClass.list_RegisteredStudents.ToArray();

            Stream stream = null;
            Student studentToAdd = null;
            try
            {
                stream = File.Open(GlobalVariablesClass.file_StudentRegistered, FileMode.OpenOrCreate);
                BinaryFormatter bf = new BinaryFormatter();
                for (int i=0;i<arrStud.Length;i++)
                {
                    bf.Serialize(stream, arrStud[i]);
                }
            }
            catch (FileNotFoundException)
            {
                GlobalVariablesClass.LogError("Could not find student file [" +
                    GlobalVariablesClass.file_StudentRegistered + "]");
            }
            catch (Exception f)
            {
                if (stream != null) stream.Close();
                GlobalVariablesClass.LogError("Error while saving student file: " + f.Message);
            }

        }

        private void ui_form_Create_Account_Deactivate(object sender, EventArgs e)
        {
            
        }

        private void ui_form_Create_Account_FormClosing(object sender, FormClosingEventArgs e)
        {
            GlobalVariablesClass.ui_main_form_login.Enabled = true;
        }

        private void ui_combo_program_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void ui_picture_leave_MouseEnter(object sender, EventArgs e)
        {
            ui_picture_leave.Image = Properties.Resources.back_arrowHigh;
        }

        private void ui_picture_leave_MouseLeave(object sender, EventArgs e)
        {
            ui_picture_leave.Image = Properties.Resources.back_arrow;
        }

        private void ui_picture_leave_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void ui_form_Create_Account_MouseDown(object sender, MouseEventArgs e)
        {
            int mouseYLoc = e.Y;

            isFormDragged = false;

            if (mouseYLoc <= ui_picture_leave.Top + ui_picture_leave.Height)
            {
                formMoveXOffset = e.X;
                formMoveYOffset = e.Y;
                isFormDragged = true;
            }
        }

        private void ui_form_Create_Account_MouseUp(object sender, MouseEventArgs e)
        {
            isFormDragged = false;
        }

        private void ui_timer_formDrag_Tick(object sender, EventArgs e)
        {
            if (isFormDragged)
            {
                Left = Cursor.Position.X - formMoveXOffset;
                Top = Cursor.Position.Y - formMoveYOffset;
            }
        }

        private void ui_form_Create_Account_Move(object sender, EventArgs e)
        {

        }

    }
}

